#pragma strict

//////////////////////////////////////////////////////
///矩阵助手.
//////////////////////////////////////////////////////
class MatrixTool{
	/**
	1,0,0,0
	0,cos,sin,0
	0,-sin,cos,0
	0,0,0,1
	*/
	static function CreateRotationX(degree:float):Matrix4x4{
		var rad:float = degree * Mathf.Deg2Rad;
		var sin:float = Mathf.Sin(rad);
		var cos:float = Mathf.Cos(rad);
		
		var m:Matrix4x4 = Matrix4x4.identity;
			m.SetRow(0,Vector4(1,0,0,0));
			m.SetRow(1,Vector4(0,cos,sin,0));
			m.SetRow(2,Vector4(0,-sin,cos,0));
			m.SetRow(3,Vector4(0,0,0,1));
		return m;
	}
	/**
	cos,0,-sin,0
	0	1,0,0
	sin,0,cos,0
	0,0,0,1
	*/
	static function CreateRotationY(degree:float):Matrix4x4{
		var r:float = degree * Mathf.Deg2Rad;
		var sin:float = Mathf.Sin(r);
		var cos:float = Mathf.Cos(r);
		
		var m:Matrix4x4 = Matrix4x4.identity;
			m.SetRow(0,Vector4(cos,0,-sin,0));
			m.SetRow(1,Vector4(0,1,0,0));
			m.SetRow(2,Vector4(sin,0,cos,0));
			m.SetRow(3,Vector4(0,0,0,1));
		return m;
	}
	/**
	cos,sin,0,0
	-sin,cos,0,0
	0,0,1,0
	0,0,0,1
	*/
	static function CreateRotationZ(degree:float):Matrix4x4{
		var r:float = degree * Mathf.Deg2Rad;
		var sin:float = Mathf.Sin(r);
		var cos:float = Mathf.Cos(r);
		
		var m:Matrix4x4 = Matrix4x4.identity;
			m.SetRow(0,Vector4(cos,sin,0,0));
			m.SetRow(1,Vector4(-sin,cos,0,0));
			m.SetRow(2,Vector4(0,0,1,0));
			m.SetRow(3,Vector4(0,0,0,1));
		return m;
	}
	/**
	将4x4矩阵转换成四元数
	*/
	static function ToQuaternion(m:Matrix4x4):Quaternion{
		var m11:float = m[0,0]; var m12:float = m[0,1]; var m13:float = m[0,2];
		var m21:float = m[1,0]; var m22:float = m[1,1]; var m23:float = m[1,2];
		var m31:float = m[2,0]; var m32:float = m[2,1]; var m33:float = m[2,2];
	
		var fourWSquaredMinus1 = m11 + m22 + m33;
		var fourXSquaredMinus1 = m11 - m22 - m33;
		var fourYSquaredMinus1 = m22 - m11 - m33;
		var fourZSquaredMinus1 = m33 - m11 - m22;
		var biggestIndex:int = 0;
		var fourBiggestSquaredMinus1:float = fourWSquaredMinus1;
		if(fourXSquaredMinus1 > fourBiggestSquaredMinus1){
			fourBiggestSquaredMinus1 = fourXSquaredMinus1;
			biggestIndex = 1;
		}
		if(fourYSquaredMinus1 > fourBiggestSquaredMinus1){
			fourBiggestSquaredMinus1 = fourYSquaredMinus1;
			biggestIndex = 2;
		}
		if(fourZSquaredMinus1 > fourBiggestSquaredMinus1){
			fourBiggestSquaredMinus1 = fourZSquaredMinus1;
			biggestIndex = 3;
		}
		//计算平方根和除法
		var biggestVal:float = Mathf.Sqrt(fourBiggestSquaredMinus1 + 1.0f) * 0.5f;
		var mult:float = 0.25f / biggestVal;
		//计算四元数的值
		var x:float;
		var y:float;
		var z:float;
		var w:float;
		switch(biggestIndex){
			case 0:
				w = biggestVal;
				x = (m23 - m32) * mult;
				y = (m31 - m13) * mult;
				z = (m12 - m21) * mult;
			break;
			case 1:
				x = biggestVal;
				w = (m23 - m32) * mult;
				y = (m12 + m21) * mult;
				z = (m31 + m13) * mult;
			break;
			case 2:
				y = biggestVal;
				w = (m31 - m13) * mult;
				x = (m12 + m21) * mult;
				z = (m23 + m32) * mult;
			break;
			case 3:
				z = biggestVal;
				w = (m12 - m21) * mult;
				x = (m31 + m13) * mult;
				y = (m23 + m32) * mult;
			break;
		}
		return Quaternion(x,y,z,w);
	}
	/**
	绕x轴旋转的矩阵
	*/
	static function RotX(degree:float):Matrix4x4{
		var p:Vector3 = Vector3.zero;
		var q:Quaternion = QuaternionTool.AxisAngle(Vector3.right,degree);
			q = Quaternion.Inverse(q);
		var s:Vector3 = Vector3(1,1,1);
		return Matrix4x4.TRS(p,q,s);
	}
	/**
	绕y轴旋转的矩阵
	*/
	static function RotY(degree:float):Matrix4x4{
		var p:Vector3 = Vector3.zero;
		var q:Quaternion = QuaternionTool.AxisAngle(Vector3.up,degree);
			q = Quaternion.Inverse(q);
		var s:Vector3 = Vector3(1,1,1);
		return Matrix4x4.TRS(p,q,s);
	}
	/**
	绕z轴旋转的矩阵
	*/
	static function RotZ(degree:float):Matrix4x4{
		var p:Vector3 = Vector3.zero;
		var q:Quaternion = QuaternionTool.AxisAngle(Vector3.forward,degree);
			q = Quaternion.Inverse(q);
		var s:Vector3 = Vector3(1,1,1);
		return Matrix4x4.TRS(p,q,s);
	}
}